package com.qww.supplement.singleton.type1;

/**
 * 懒汉式单例
 *
 * 1. 构造器私有化。
 * 2. 开始一上来，不像饿汉式单例那样，就直接在类加载时创建对象，而是在调用getInstance*()方法且instanc为null时才创建对象。
 * 3. 在向外部提供对象引用的静态方法体中，对对象引用做null判断，如果为null才创建对象对该私有字段进行初始化，最后将对象引用返回。
 * 4. 同时考虑到要工作在多线程环境下，对多个线程会创建多个对象，所以需要使用synchronized进行同步。
 */
public class LazyMan {
    private LazyMan() {
        System.out.println(Thread.currentThread().getName() + " ok!");
    }

    private static LazyMan instance;
    // 静态工厂方法
    public static LazyMan getInstance() {
        /*
            这在多线程环境下，是线程不安全的，会出现多个LazyMan实例
            如果一个线程进入if (instance == null)判断语句，刚刚通过。还没有来得及执行下面的语句
            而另一个线程也通过if判断语句，那么就会出现两个线程同时执行instance = new LazyMan();语句
            从而出现多个实例。
         */
        /*
        if (instance == null) {
            synchronized (LazyMan.class) {
                instance = new LazyMan();
            }
        }
        */
        synchronized (LazyMan.class) {
            if (instance == null) {
                instance = new LazyMan();
            }
        }
        return instance;
    }

    // 测试
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    LazyMan instance = LazyMan.getInstance();
                }
            }).start();
        }
    }
}
